# coding: utf-8

import redis
from datadefs import Item

class RedisAccess(object):
    '''
    Класс RedisAccess. Скрывает дополнительную функциональность для работы с
    базой данных Redis. Снабжен несколькими функциями для получения списка
    продуктов, категорий и секций.
    
    На данный момент представляет собой попытку представить все возможные
    функции, которые в будущем могут пригодиться в проекте.'''
    
    def __init__(self, adress):
        '''
        Когда создается класс RedisAccess, автоматически создается объект
        redis.Redis, который обеспечивает доступ к данным.'''
        self.connection = redis.Redis(adress)
        self.working_revision = None
        
    def category(self, name):
        return self.connection.hget('global:categories', name)
        
    def section(self, name):
        return self.connection.hget('global:sections', name)
        
    def create_section(self, name):
        sectionid = self.connection.incr('global:next:section')
        prefix = 'section:{0}:'.format(sectionid)
        self.connection.hset('global:sections', name, sectionid)
        self.connection.set(prefix + 'name', name)
        return sectionid
        
    def create_category(self, sectionid, name):
        categoryid = self.connection.incr('global:next:category')
        prefix = 'category:{0}:'.format(categoryid)
        self.connection.hset('global:categories', name, categoryid)
        self.connection.set(prefix + 'name', name)
        return categoryid
        
    def register_store(self, name, adress):
        storeid = self.connection.incr('global:next:store')
        prefix = 'store:{0}:'.format(storeid)
        self.connection.set(prefix + 'name', name)
        self.connection.set(prefix + 'adress', adress)
        
    # Возможность получить информацию о выбранном товаре в виде объекта Item.
    def get_item(self, itemid):
        prefix = 'item:{0}:'.format(itemid)
        descr = self.connection.hgetall(prefix + 'description')
        # presenceids = self.connection.smembers(prefix + 'presence') # TODO
        item = Item()
        item.description = descr
        return item        
    
    # Возможность получить список id объектов для выбранной секции.
    def category_contents(self, name):
        items = []
        if self.category(name) is not None:
            cid = self.connection.hget('global:categories', name)
            items = self.connection.smembers('category:{0}:set'.format(cid))
        return items
        
    # Проследить историю обновлений для текущего id (фича на будущее).
    def get_history(self, itemid):
        raise NotImplementedError
        
    # Установить рабочую ревизию.
    def set_working_revision(self, date):
        revision = self.connection.incr('global:next:revision')
        prefix = 'revision:{0}:'.format(revision)
        self.connection.rpush('global:revisions', revision)
        self.connection.set(prefix + 'date', date)
        self.working_revision = revision
        
    # Добавить элемент в базу.
    def add_item(self, categoryid, item, prices):
        itemid = self.connection.incr('global:next:id')
        prefix = 'item:{0}:'.format(itemid)
        for (prop, value) in item.description.items():
            self.connection.hset(prefix + 'description', prop, value)
            
        for (store, price) in prices.items():
            self.connection.hset(prefix + 'prices', store, price)
        
        self.connection.set(prefix + 'previd', 0) # TODO previd
        self.connection.set(prefix + 'revision', self.working_revision)
        
        self.connection.sadd(
          'revision:{0}:set'.format(self.working_revision), itemid)
        self.connection.sadd('category:{0}:set'.format(categoryid), itemid)
        
    # Создать категории и секции согласно дереву.
    def perform_tree(self, tree):
        for section in tree.getlist():
            sectionid = self.section(section.title())
            if sectionid is None:
                sectionid = self.create_section(section.title())
            for category in section.getlist():
                categoryid = self.category(category.title())
                if categoryid is None:
                    categoryid = self.create_category(sectionid, category.title())
                for each in category.products:
                    self.add_item(categoryid, each, prices={}) # TODO prices
                    
    def get_latest_revision(self):
        step = (-1) if self.working_revision in None else (-2)
        revisionid = self.lindex('global:revisions', step)
        return self.connection.smembers('revision:{0}:set'.format(revisionid))
